<?php namespace App\Repositories\Eloquent\Order;

use App\Exceptions\Item\OrderException;
use App\Models\ItemOrder;
use App\Models\ItemOrderAppeal;
use App\Models\ItemOrderMessage;
use App\Repositories\Eloquent\Order\Entity\PayParams;
use App\Repositories\Order\OrderRepositoryInterface;
use Illuminate\Database\Eloquent\ModelNotFoundException;

class OrderRepository implements OrderRepositoryInterface
{
    /**
     * 获取订单详情
     *
     * @param $id
     *
     * @return \Illuminate\Database\Eloquent\Collection|\App\Models\ItemOrder|\App\Models\ItemOrder[]
     */
    public function show($id)
    {
        return ItemOrder::query()->find($id);
    }

    /**
     * 查询消息，如果查询不到，这抛出异常
     *
     * @param $id
     *
     * @return \Illuminate\Database\Eloquent\Collection|\App\Models\ItemOrder|\App\Models\ItemOrder[]
     * @throws OrderException
     */
    public function showWithThrow($id)
    {
        try {
            return ItemOrder::query()->findOrFail($id);
        } catch (ModelNotFoundException $e) {
            throw new OrderException(OrderException::NOT_FOUND);
        }
    }

    /**
     * 通过订单编号获取订单
     *
     * @param $trade_no
     *
     * @return \App\Models\ItemOrder
     */
    public function showByTradeNo($trade_no)
    {
        return ItemOrder::query()
            ->where('trade_no', $trade_no)
            ->first();
    }

    /**
     * 创建订单
     *
     * @param PayParams $pay
     *
     * @return \App\Models\ItemOrder
     */
    public function create(PayParams $pay)
    {
        $model = new ItemOrder();
        $model->user_id = $pay->user_id;
        $model->item_id = $pay->item_id;
        $model->publisher_uid = $pay->publisher_uid;
        $model->money = $pay->money;
        $model->status = ItemOrder::PAY_PENDING;
        $model->trade_no = $this->createRandomTradeNo();

        $model->save();

        return $model;
    }

    /**
     * 用户订单列表
     *
     * @param $user_id
     *
     * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator
     */
    public function userOrders($user_id, $per_page)
    {
        return ItemOrder::query()
            ->where('user_id', $user_id)
            ->where('status', ItemOrder::PAID_SUCCESS)
            ->orderByDesc('created_at')
            ->paginate($per_page);
    }

    /**
     * 发布者订单列表
     *
     * @param $publisher_uid
     *
     * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator
     */
    public function publisherOrders($publisher_uid, $per_page)
    {
        return ItemOrder::query()
            ->where('publisher_uid', $publisher_uid)
            ->where('status', ItemOrder::PAID_SUCCESS)
            ->orderByDesc('created_at')
            ->paginate($per_page);
    }

    /**
     * 随机生成交易订单编号
     *
     * @return string
     */
    private function createRandomTradeNo()
    {
        //时间：14位
        $trade_no = date('YmdHis');

        //毫秒：4位
        list($usec, $sec) = explode(" ", microtime());
        $trade_no .= sprintf('%04d', $usec * 10000);

        //随机：2位
        $trade_no .= sprintf('%02d', mt_rand(1, 99));

        return $trade_no;
    }

    /**
     * 创建订单申诉
     *
     * @param $id
     * @param $content
     *
     * @return ItemOrderAppeal
     */
    public function storeOrderAppeal($id, $content)
    {
        $order = $this->showWithThrow($id);

        $model = new ItemOrderAppeal();
        $model->order_id = $id;
        $model->user_id = $order->user_id;
        $model->publisher_uid = $order->publisher_uid;
        $model->content = $content;
        $model->status = ItemOrderAppeal::PENDING_CHECK;
        $model->save();

        return $model;
    }

    /**
     * 订单的申诉记录
     *
     * @param $order_id
     *
     * @return \Illuminate\Database\Eloquent\Model|null|static
     */
    public function orderAppeal($order_id)
    {
        return ItemOrderAppeal::query()->where(compact('order_id'))->first();
    }

    /**
     * 用户订单留言
     *
     * @param $id
     * @param $content
     *
     * @return ItemOrderMessage
     */
    public function storeUserMessage($id, $content)
    {
        $order = $this->showWithThrow($id);

        $model = new ItemOrderMessage();
        $model->order_id = $id;
        $model->user_id = $order->user_id;
        $model->content = $content;
        $model->save();

        return $model;
    }

    /**
     * 获取用户订单留言
     *
     * @param $order_id
     *
     * @return \Illuminate\Database\Eloquent\Model|null|static
     */
    public function orderMessage($order_id)
    {
        return ItemOrderMessage::query()->where(compact('order_id'))->first();
    }

    /**
     * 是否购买了该信息
     *
     * @param $user_id
     * @param $item_id
     *
     * @return bool
     */
    public function isPaidItem($user_id, $item_id)
    {
        return ItemOrder::query()
                ->where('user_id', (int)$user_id)
                ->where('item_id', (int)$item_id)
                ->where('status', ItemOrder::PAID_SUCCESS)
                ->count() > 0;
    }

    /**
     * 支付成功
     *
     * @param $order
     * @param $pay_order_id
     * @param $end_time
     *
     * @return bool
     */
    public function paySuccess($order, $pay_order_id, $end_time)
    {
        if (!$order instanceof ItemOrder) {
            $order = $this->showByTradeNo((string)$order);
        }

        $order->status = ItemOrder::PAID_SUCCESS;
        $order->pay_trade_no = $pay_order_id;
        $order->pay_end_time = $end_time;

        return $order->save();
    }

    /**
     * 支付失败
     *
     * @param $order
     * @param $out_trade_no
     * @param $end_time
     *
     * @return bool
     */
    public function payFailure($order, $out_trade_no, $end_time)
    {
        if (!$order instanceof ItemOrder) {
            $order = $this->showByTradeNo((string)$order);
        } else {
            $order = $this->show($order->id);
        }

        if ($order->isPaidSuccess()) {
            return false;
        }

        $order->status = ItemOrder::PAID_FAILURE;
        $order->pay_trade_no = $out_trade_no;
        $order->pay_end_time = date('Y-m-d H:i:s', $end_time);

        return $order->save();
    }

}
